/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.webhomesites.padrao.utils;

/**
 *
 * @author Webhome
 */
import br.com.webhomesites.configuracao.infra.EntityUtil;
import br.com.webhomesites.padrao.contracts.IGenericDAO;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.swing.JOptionPane;
import javax.validation.Valid;
import org.hibernate.EntityMode;
import org.hibernate.Session;
 
@SuppressWarnings("unchecked")
public class GenericDAO<T extends AbstractEntity> implements IGenericDAO<T> {
 
    protected static EntityManager entityManager;
    public static final Session session;
 
    static {
        entityManager = EntityUtil.getNewEntityManager();
        session = EntityUtil.getNewSession();
    }
 
    @Override
    public T getById(Long id) {
        return (T) entityManager.find(getTypeClass(), id);
    }
    
    public long getMaxId() {
         Query query = getEntityCriada().createNamedQuery(getTypeClass().getName()+".findMaxId");
         if(query.getSingleResult()==null){
             return 0;
         } else {
         Long retorno = (Long) query.getSingleResult();
         return retorno;
         }
    }
    
    public long getIdByDescricao(String descricao) {
         Query query = getEntityCriada().createNamedQuery(getTypeClass().getName()+".findIdByDescricao");
         query.setParameter("descricao", descricao);
         Long retorno = (Long) query.getSingleResult();
         return retorno;
    }
    
    public List<T> findByDescricao(String descricao) {
        Query query = getEntityCriada().createNamedQuery(getTypeClass().getName()+".findByDescricao");
        query.setParameter("descricao", descricao);
        List<T> retorno = query.getResultList();
        return retorno;
    }
    
    public T findByDescricaoUnica(String descricao) {
        Query query = getEntityCriada().createNamedQuery(getTypeClass().getName()+".findByDescricaoUnica");
        query.setParameter("descricao", descricao);
        T retorno = (T) query.getSingleResult();
        return retorno;
    }
     
    @Override
    public void save(@Valid T entity) {
        try {
            
            entityManager.getTransaction().begin();
            //session.save(entity);
            entityManager.persist(entity);
            entityManager.flush();
            //session.flush();
            entityManager.getTransaction().commit();
            //session.clear();
            entityManager.clear();
            
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "Verifique se este produto está composto!");
            e.printStackTrace();
            entityManager.getTransaction().rollback();
        }
    }
 
    @Override
    public void update(T entity) {
        try {
            entityManager.getTransaction().begin();
            entityManager.merge(entity);
            entityManager.flush();
            entityManager.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            entityManager.getTransaction().rollback();
        }
    }
 
    @Override
    public void delete(T entity) {
        try {
            entity = getById(entity.getId());
            entityManager.getTransaction().begin();
            entityManager.remove(entity);
            entityManager.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            entityManager.getTransaction().rollback();
        }
    }
 
    @Override
    public List<T> findAll() {
        return entityManager.createQuery(("From " + getTypeClass().getName()))
                .getResultList();
    }
    
    public EntityManager getEntityCriada() {
        return entityManager;
    }
 
    private Class<?> getTypeClass() {
        Class<?> clazz = (Class<?>) ((ParameterizedType) this.getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
        return clazz;
    }
}